'''
Created on Oct 19,  2009

@author: paul
'''
from sql_utils import SQLScriptRunner
from copy import copy
from xml.sax import parse
from xml.sax.handler import ContentHandler
import logging

_LOGGER  =  logging.getLogger("mx.org.came.schema_reader")

class ApplicationReader():
    '''This class is called whenever SMSAppStore needs to know the application
    description.
    '''
    
    def __init__(self,  db_connection_factory):
        self._db_connection_factory  =  db_connection_factory
    
    def parse_file(self,  app_id):
        my_handler = AppHandler()
        my_sql = SQLScriptRunner(self._db_connection_factory)
        path = my_sql.get_application_descriptor_path(app_id)
        _LOGGER.debug(path)
        path  =  path[0][0]
        with open(path, 'r') as spec:
            parse(spec, my_handler)
            spec.close()
        return my_handler.app_dict

class FormReader():
    '''
    This class is called whenever SMSAppStore needs to know the form description
    '''

    def __init__(self,  db_connection_factory):
        self._db_connection_factory  =  db_connection_factory

    def parse_file(self, aid, fid):
        my_handler = FormHandler()
        my_sql = SQLScriptRunner(self._db_connection_factory)
        path = my_sql.get_form_descriptor_path(aid, fid)
        _LOGGER.debug(path)
        path = path[0][0]
        with open(path, 'r') as spec:
            parse(spec, my_handler)
            spec.close()
        return my_handler.form_dict
    
class AppHandler(ContentHandler):

    # This value in the 'range' attribute of a field attribute indicates
    # that the contents is a string.
    STR_FIELD_RANGE  =  0

    # This value in the 'range' attribute of a field attribute indicates
    # that the contents is a date.
    DATE_FIELD_RANGE  =  -1

    # This value in the 'range' attribute of a field attribute indicates
    # that the contents is 'multiple choice'.
    MC_FIELD_RANGE  =  -2

    # This value in the 'range' attribute of a field attribute indicates
    # that the contents is 'single choice' (i.e. boolean).
    SC_FIELD_RANGE  =  -3

    
    #These are CLASS VARIABLE By default is PUBLIC
    global app_dict, schemas_dict, fields_dict 
    global current_field_id, current_schema_name 
    global current_schema_id
    
    def __init__(self):
        self.app_dict = {}
        self.schemas_dict = {}
        self.fields_dict = {}
        self.app_dict['schemas'] = self.schemas_dict
    
    def startElement(self, name, attrs): 
        if name  ==  'application': 
            name_list = attrs.getNames()
            for i in range(len(name_list)):
                self.app_dict[name_list[i]] = attrs.getValue(name_list[i])
        if name  ==  'schema':
            self.current_schema_id = attrs.getValue('id')
            self.current_schema_name = attrs.getValue('name')
        if name  ==  'field':
            field = {}
            field['name'] = attrs.getValue('name')
            #field['type'] = attrs.getValue('type')
            field['range'] = attrs.getValue('range')
            self.fields_dict[attrs.getValue('id')] = field
            self.current_field_id = attrs.getValue('id')
        if name  ==  'choice':
            field = self.fields_dict[self.current_field_id]
            if 'choice' in field:
                choice_list = field['choice']
                choice_list.append(attrs.getValue('name'))
                self.fields_dict[self.current_field_id] = field
            else:
                choice_list = [attrs.getValue('name')]
                field['choice'] = choice_list
                self.fields_dict[self.current_field_id] = field
    
    def endElement(self, name):
        if name  ==  'schema': 
            self.fields_dict['name'] = self.current_schema_name
            self.schemas_dict[self.current_schema_id] = self.fields_dict.copy()
            self.fields_dict.clear()
            
class FormHandler(ContentHandler):
    
    # This value in the 'operation' attribute of a form descriptor
    # identifies a 'create' operation.
    OP_CREATE_ID  =  0

    # This value in the 'operation' attribute of a form descriptor
    # identifies an update operation.
    OP_UPDATE_ID  =  1

    # This value in the 'operation' attribute of a form descriptor
    # identifies a destroy operation.
    OP_DESTROY_ID  =  2

    # This value in the 'operation' attribute of a form descriptor
    # identifies a search operation.
    OP_SEARCH_ID  =  3

    # This value in the 'operation' attribute of a form descriptor
    # identifies an 'advanced search' operation.
    OP_ADV_SEARCH_ID  =  4

    # This value in the 'operation' attribute of a form descriptor
    # identifies a 'CAME payment' operation.
    OP_CAME_PAYMENT  =  5

    
    #These are CLASS VARIABLE By default is PUBLIC
    global form_dict, schemas_dict, fields_dict, fields_list, fetchoice_list 
    global operation_dict, current_schema_id, is_fetch_operation, is_fetch_field
    
    def __init__(self):
        self.form_dict = {}
        self.schemas_dict = {}
        self.fields_dict = {}
        self.operation_dict = {}
        self.fields_list = []
        self.fetchoice_list = []
        self.fields_dict['fields'] = self.fields_list
        self.fields_dict['fetch'] = self.fetchoice_list
        self.form_dict['schemas'] = self.schemas_dict
        #self.form_dict['operator'] = self.operation_dict
        self.is_fetch_operation = False
        self.is_fetch_field = False
    
    def startElement(self, name, attrs): 
        if name  ==  'form': 
            name_list = attrs.getNames()
            for i in range(len(name_list)):
                self.form_dict[name_list[i]] = attrs.getValue(name_list[i])
            if self.form_dict['operation']   ==   \
                                str(FormHandler.OP_SEARCH_ID) \
                    or self.form_dict['operation']   ==   \
                            str(FormHandler.OP_ADV_SEARCH_ID):
                self.is_fetch_operation = True
        if name  ==  'schema':
            self.current_schema_id = attrs.getValue('id')
            self.fields_list = []
            self.fetchoice_list = []
            self.fields_dict.clear()
            self.fields_dict['fields'] = self.fields_list
            self.fields_dict['fetch'] = self.fetchoice_list
            self.fields_dict['operator'] = self.operation_dict
        if name  ==  'fields' and self.is_fetch_operation:
            self.form_dict['logical'] = attrs.getValue('logical')
        if name  ==  'field':
            if self.is_fetch_field:
                self.fetchoice_list.append(attrs.getValue('id'))
            elif self.is_fetch_operation:
                self.fields_list.append(attrs.getValue('id'))
                self.operation_dict[attrs.getValue('id')] = \
                                 attrs.getValue('operator')
            else:
                self.fields_list.append(attrs.getValue('id'))
        if name  ==  'fetch':
            self.is_fetch_field = True
    
    def endElement(self, name):
        if name  ==  'schema': 
            self.schemas_dict[self.current_schema_id] = copy(self.fields_dict)
            #self.schemas_dict[self.current_schema_id]
